/*!
 * \file ast_omega_syntax_visitor.cc
 *
 * \brief Implementation of the omega syntax generation visitor for ast.
 *
 * \date Started: 7/12/2010
 * \date Last Modified: 7/27/2010
 * \authors Alan LaMielle
 * \authors Ian Craig
 * \authors Nicholas Jeanette
 *
 * Copyright (c) 2010, Colorado State University <br>
 * All rights reserved. <br>
 * See ../../COPYING for details. <br>
 */

#include <iegenlib/iegenlib.h>

namespace iegenlib{

/***************Omega Syntax*************/
void OmegaSyntax::PresSetCase(PresSet* node){
  const list<string>* syms=node->getSymbolics();
  if(syms->begin() != syms->end()){
     original +="[";
     for(list<string>::const_iterator itr = syms->begin(); itr != syms->end(); itr++){
     original += (*itr);
     original += ",";
     }
     original = original.substr(0, original.size()-1);
     original += "]->";
  }
  original += "{";
  this->PresSetIn(node);
  node->applyConjunct(this);
  this->PresSetOut(node);
  for(list<string>::iterator itr = conj_list.begin(); itr != conj_list.end(); itr++){
     original += (*itr);
     original += "; ";
  }
  original = original.substr(0, original.size()-2);
  original += "}";
}

void OmegaSyntax::PresRelationCase(PresRelation* node){
  const list<string>* syms=node->getSymbolics();
  if(syms->begin() != syms->end()){
     original +="[";
     for(list<string>::const_iterator itr = syms->begin(); itr != syms->end(); itr++){
     original += (*itr);
     original += ",";
     }
     original = original.substr(0, original.size()-1);
     original += "]->";
  }
  original += "{";
  this->PresRelationIn(node);
  node->applyConjunct(this);
  this->PresRelationOut(node);
  for(list<string>::iterator itr = conj_list.begin(); itr != conj_list.end(); itr++){
     original += (*itr);
     original += "; ";
  }
  original = original.substr(0, original.size()-2);
  original += "}";
}

void OmegaSyntax::VarTupleIn(VarTuple* node){
  original1 += "[";
}

void OmegaSyntax::VarTupleCase(VarTuple* node){
  this->VarTupleIn(node);
  bool first = true;
  for(list<VarExp*>::iterator itr = node->begin(); itr != node->end(); ++itr){
    if(!first){
      original1+= ",";
    }else{
      first = false;
    }
    (*itr)->apply(this);
  }
  this->VarTupleOut(node);
}

void OmegaSyntax::VarTupleOut(VarTuple* node){
  original1 += "]";
}

void OmegaSyntax::VarExpIn(VarExp* node){
  if(node->getCoeff() != 1 && node->getCoeff() != 0){
    string coeffString;
    stringstream str;
    if(node->getCoeff() != -1){
      str << node->getCoeff();
    }else{
      str << "-";
    }
    coeffString = str.str();
    if(node->getCoeff() < 0 && original1.at(original1.size()-1) == '+'){
      original1 = original1.substr(0, original1.size()-1);
    }
    original1 += coeffString;
  }
  if(node->getCoeff() != 0){
    original1 += node->getId();
  }else{
    original1 += "0";
  }
}

void OmegaSyntax::FuncExpIn(FuncExp* node){
  if(node->getCoeff() != 1 && node->getCoeff() != 0){
    string coeffString;
    stringstream str;
    if(node->getCoeff() != -1){
      str << node->getCoeff();
    }else{
      str << "-";
    }
    coeffString = str.str();
    if(node->getCoeff() < 0 && original1.at(original1.size()-1) == '+'){
      original1 = original1.substr(0, original1.size()-1);
    }
    original1 += coeffString;
  }
}

void OmegaSyntax::FuncExpCase(FuncExp* node){
  this->FuncExpIn(node);
  if(node->getCoeff() != 0){
    original1 += node->getName();
    original1 += "(";
    for(list<NormExp*>::iterator itr = node->begin(); itr != node->end(); ++itr){
      (*itr)->apply(this);
      original1 += ",";
    }
    original1 = original1.substr(0,original1.length()-1) + ")";
  }
  this->FuncExpOut(node);
}

void OmegaSyntax::NormExpCase(NormExp* node){
  this->NormExpIn(node);
  bool first = true;
  for(list<Expression*>::iterator itr = node->begin(); itr != node->end(); ++itr){
    if(first){
      first = false;
    }else{
      original1 += "+";
    }
    (*itr)->apply(this);
  }
  this->NormExpOut(node);
}

void OmegaSyntax::NormExpOut(NormExp* node){
  if(node->getConst() != 0 && node->getConst() != 0){
    if(node->getConst() > 0){
      original1 += "+";
    }
    string conString;
    stringstream str;
    str << node->getConst();
    conString = str.str();
    original1 += conString;
  }
}

void OmegaSyntax::InequalityOut(Inequality* node){
  original1 += ">=0";
}

void OmegaSyntax::EqualityOut(Equality* node){
  original1 += "=0";
}

void OmegaSyntax::ConjunctionCase(Conjunction* node){
  original1="";
  ConjunctionIn(node);
  bool first = true;
  if(node->getOutVars()==NULL){
    node->applyVars(this);
  }
  else{
    node->applyInVars(this);
    original1 += "->";
    node->applyOutVars(this);
  }
  if(node->constraintSize() > 0){
    original1 += ":";
    for(list<Constraint*>::iterator itr = node->begin(); itr != node->end(); ++itr){
      if(first){
        first = false;
      }else{
        original1 += " and ";
      }
      (*itr)->apply(this);
    }
  }
  ConjunctionOut(node);
  conj_list.push_back(original1);
}
/****************************************/

}//end namespace iegenlib
